package com.ultrasoft.farmasoft.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ultrasoft.farmasoft.domain.Activesubstance;
import com.ultrasoft.farmasoft.domain.Attribute;
import com.ultrasoft.farmasoft.domain.Composition;
import com.ultrasoft.farmasoft.domain.Genericvalue;
import com.ultrasoft.farmasoft.domain.Item;
import com.ultrasoft.farmasoft.domain.Package;
import com.ultrasoft.farmasoft.domain.Pharmacy;
import com.ultrasoft.farmasoft.domain.Pharmacyproduct;
import com.ultrasoft.farmasoft.domain.Product;
import com.ultrasoft.farmasoft.domain.Productattribute;
import com.ultrasoft.farmasoft.domain.Productattributes;
import com.ultrasoft.farmasoft.domain.Provider;
import com.ultrasoft.farmasoft.domain.Providerpharmacy;
import com.ultrasoft.farmasoft.domain.Typecomposition;
import com.ultrasoft.farmasoft.repository.ActiveSubstanceDao;
import com.ultrasoft.farmasoft.repository.AttributeDao;
import com.ultrasoft.farmasoft.repository.CompositionDao;
import com.ultrasoft.farmasoft.repository.GenericValueDao;
import com.ultrasoft.farmasoft.repository.ItemDao;
import com.ultrasoft.farmasoft.repository.PackageDao;
import com.ultrasoft.farmasoft.repository.PharmacyDao;
import com.ultrasoft.farmasoft.repository.PharmacyProductDao;
import com.ultrasoft.farmasoft.repository.ProductAttributeDao;
import com.ultrasoft.farmasoft.repository.ProductAttributesDao;
import com.ultrasoft.farmasoft.repository.ProductDao;
import com.ultrasoft.farmasoft.repository.ProviderDao;
import com.ultrasoft.farmasoft.repository.ProviderPharmacyDao;
import com.ultrasoft.farmasoft.repository.TypeCompositionDao;


@Service
public class ConfigServiceProductsImpl implements ConfigServiceProducts {

	private TypeCompositionDao typeCompositionDao;
	private ActiveSubstanceDao activeSubstanceDao;
	private AttributeDao attributeDao;
	private CompositionDao compositionDao;
	private ProductAttributeDao productAttributeDao;
	private ProductDao productDao;
	private ProviderDao providerDao;
	private GenericValueDao genericValueDao;
	private ProductAttributesDao productAttributesDao;
	private ProviderPharmacyDao providerPharmacyDao;
	private PharmacyDao pharmacyDao;
	private PharmacyProductDao pharmacyProductDao;
	private PackageDao packageDao;
	private ItemDao itemDao;
	
	@Autowired
    public ConfigServiceProductsImpl(ItemDao itemDao,PackageDao packageDao,PharmacyProductDao pharmacyProductDao,PharmacyDao pharmacyDao,ProviderPharmacyDao providerPharmacyDao,ProductAttributesDao productAttributesDao,GenericValueDao genericValueDao,ProviderDao providerDao,ProductDao productDao,ProductAttributeDao productAttributeDao,CompositionDao compositionDao,TypeCompositionDao typeCompositionDao, ActiveSubstanceDao activeSubstanceDao, AttributeDao attributeDao){
    	this.typeCompositionDao		= typeCompositionDao;
    	this.activeSubstanceDao		= activeSubstanceDao;
    	this.attributeDao			= attributeDao;
    	this.compositionDao 		= compositionDao;
    	this.productAttributeDao	= productAttributeDao;
    	this.productDao 			= productDao;
    	this.providerDao 			= providerDao;
    	this.genericValueDao 		= genericValueDao;
    	this.productAttributesDao 	= productAttributesDao;
    	this.providerPharmacyDao 	= providerPharmacyDao;
    	this.pharmacyDao 			= pharmacyDao;
    	this.pharmacyProductDao 	= pharmacyProductDao;
    	this.packageDao				= packageDao;
    	this.itemDao 				= itemDao;
	}



// start Typecomposition
 /*
    @Transactional(readOnly = true)
    public List<Typecomposition> getTypecompositionList(boolean active){
    	return typeCompositionDao.getTypecompositionList(active);
    }
    */
 
    @Transactional(readOnly = true)
    public List<Typecomposition> getTypecompositionList(){
    	return typeCompositionDao.getTypecompositionList();
    }    
    @Transactional
    public void addTypeComposition(Typecomposition typeComposition){
    	typeCompositionDao.add(typeComposition);
    }
    @Transactional
    public void removeTypeComposition(Typecomposition typeComposition){
    	typeCompositionDao.remove(typeComposition);
    }  
    @Transactional
    public void updateTypeComposition(Typecomposition typeComposition){
    	typeCompositionDao.update(typeComposition);
    }  
    @Transactional(readOnly = true)
    public Typecomposition searchTypecompositionByID(Integer idTypeComposition){
		return typeCompositionDao.findTypecompositionByID(idTypeComposition);
	}
    // end Typecomposition
    
    
    
    
 // start ActiveSubstance
    /*
       @Transactional(readOnly = true)
       public List<Typecomposition> getTypecompositionList(boolean active){
       	return typeCompositionDao.getTypecompositionList(active);
       }
       */
    @Transactional(readOnly = true)
    public Integer getSubstanceActiveId(){
		return activeSubstanceDao.getSubstanceActiveId();
	}
    
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void saveSubstanceActive(Activesubstance activesubstance)throws Exception{
    	try {
    		activeSubstanceDao.add(activesubstance);
    	} catch (Exception e) {
    	      throw e;
    	}
    }
    
    @Transactional(readOnly = true)
    public List<Activesubstance> getActivesubstanceList(){
    	return activeSubstanceDao.getActivesubstanceList();
    }
          
    @Transactional
    public void addActiveSubstance(Activesubstance activeSubstance){
    	activeSubstanceDao.add(activeSubstance);
    }
    @Transactional
    public void removeActiveSubstance(Activesubstance activeSubstance){
    	activeSubstanceDao.remove(activeSubstance);
    }  
    @Transactional
    public void updateActiveSubstance(Activesubstance activeSubstance){
    	activeSubstanceDao.update(activeSubstance);
    }  
    @Transactional(readOnly = true)
    public Activesubstance searchActivesubstanceByID(Integer idActiveSubstance){
    	return activeSubstanceDao.findActiveSubstanceByID(idActiveSubstance);
   	}
       // end ActiveSubstance
    
       
       
       
       // start Attribute
       /*
          @Transactional(readOnly = true)
          public List<Typecomposition> getTypecompositionList(boolean active){
          	return typeCompositionDao.getTypecompositionList(active);
          }
          */
         
    @Transactional(readOnly = true)
    public List<Attribute> getAttribute(){
    	return attributeDao.getAttribute();
   	}
    @Transactional(readOnly = true)
   	public List<Attribute> getAttributeListByActiveSubstanceId(Integer idActiveSubstance){
   		return attributeDao.getAttributeListByActiveSubstanceId(idActiveSubstance);
   	}	       
    @Transactional(readOnly = true)
    public Attribute searchAttributeByIDActiveSubstanceAndIDAttribute(Integer idAttribute,Integer idActiveSubstance){
    	return attributeDao.findAttributeByIDActiveSubstanceAndIDAttribute(idAttribute,idActiveSubstance);
    }
    @Transactional(readOnly = true)
    public Attribute searchAttributeByID(Integer idAttribute){
    	return attributeDao.findAttributeByID(idAttribute);
    }
    @Transactional
   	public void addAttribute(Attribute attribute){
   		attributeDao.add(attribute);
   	}
    @Transactional
   	public void updateAttribute(Attribute attribute) {
   		attributeDao.update(attribute);
   	}
    @Transactional
   	public void removeAttribute(Attribute attribute) {
   		attributeDao.remove(attribute);
   	}    
    
    @Transactional(readOnly = true)
    public Integer getAttributeId(){
		return attributeDao.getAttributeId();
	}
          // end Attribute
       
		
    
    
    
    @Transactional(readOnly = true)
    public List<Provider> getListProvider(Integer pharmacyId,boolean active){
    	List<Provider> listProvider = providerDao.getListProvider(active);
    	List<Providerpharmacy> listProviderPharmacy = providerPharmacyDao.getListProviderPharmacy(pharmacyId, active);
    	List<Provider> res = new ArrayList<Provider>();
    	for (Provider provider : listProvider) {
			for (Providerpharmacy providerpharmacy : listProviderPharmacy) {
				if(providerpharmacy.getProvider().getProviderId() == provider.getProviderId() && providerpharmacy.getPharmacy().getPharmacyId() == pharmacyId){
					res.add(provider);
				}
			}
		}
       	return res;
    }
    @Transactional(readOnly = true)
    public List<Provider> getListProvider(boolean active){
    	return providerDao.getListProvider(active);
    }
    @Transactional(readOnly = true)
	public Provider searchProviderByProviderId(Integer providerId){
    	return providerDao.findProviderByProviderId(providerId);
    }	   	
    @Transactional
    public void addProvider(Provider provider){
    	providerDao.add(provider);
    }
    @Transactional
    public void updateProvider(Provider provider){
    	providerDao.update(provider);
    }
    @Transactional(readOnly = true)
	public Integer searchProviderIdByProviderIdMax(){
		return providerDao.findByProviderIdMax();
	}

    
    @Transactional(readOnly = true)   
	public List<Providerpharmacy> getListProviderPharmacyByPharmacyId(Integer pharmacyId, boolean active){
		return providerPharmacyDao.getListProviderPharmacy(pharmacyId, active);
	}
    @Transactional
    public void addProviderPharmacy(Providerpharmacy providerPharmacy){
    	providerPharmacyDao.add(providerPharmacy);
    }
    @Transactional(readOnly = true)   
	public Providerpharmacy searchProviderPharmacy(Integer pharmacyId, Integer providerId){
		return providerPharmacyDao.findProviderPharmacy(pharmacyId, providerId);
	}

	    
    
    @Transactional(readOnly = true)   
	public Pharmacy searchPharmacyByPharmacyId(Integer pharmacyId) {
		return pharmacyDao.findByPharmacyId(pharmacyId);
	}
    
    
	@Transactional(readOnly = true)
   	public List<Composition> getListComposition(){
		return compositionDao.getListComposition();
	}
	@Transactional(readOnly = true)
	public List<Composition> getListComposition(Integer compositionId,boolean active){
		return compositionDao.getListComposition(compositionId, active);
	}
	@Transactional(readOnly = true)
	public List<Composition> getListCompositionByProviderIdByProductIdByActive(Integer providerId,Integer productId,boolean active){
		return compositionDao.getListComposition(providerId, productId, active);
	}
	@Transactional(readOnly = true)
    public Composition searchCompositionByCompositionId(Integer compositionId){
		return compositionDao.findByCompositionId(compositionId);
	}
	@Transactional
	public void removeComposition(Integer providerId,Integer productId){
		compositionDao.remove(providerId, productId);
	}
	@Transactional
    public void removeComposition(Composition composition){
    	compositionDao.remove(composition);
    }
	@Transactional
    public void updateComposition(Composition composition){
		compositionDao.update(composition);
	}
	@Transactional
    public void addComposition(Composition composition){
		compositionDao.add(composition);
	}
    
	
	@Transactional(readOnly = true)
    public List<Productattribute> getListProductAttribute(){
		return productAttributeDao.getListProductAttribute();
	}
	@Transactional(readOnly = true)
    public Productattribute searchProductAttributeByProductAttributeId(Integer productAttributeId){
		return productAttributeDao.findProductAttributeByProductAttributeId(productAttributeId);
	}
	@Transactional
	public void removeProductAttribute(Productattribute productAttribute){
		productAttributeDao.remove(productAttribute);
	}
	@Transactional
    public void updateProductAttribute(Productattribute productAttribute){
		productAttributeDao.update(productAttribute);
	} 
	@Transactional
    public void addProductAttribute(Productattribute productAttribute){
		productAttributeDao.add(productAttribute);
	}
    
	
	@Transactional(readOnly = true)
    public List<Product> getListProduct(){
		return productDao.getListProduct();
	}
	@Transactional(readOnly = true)
	public List<Product> getListProduct(boolean active){
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProduct(active);
		for (Product product : listProduct) {
			product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
			product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
			res.add(product);
		}
		return res;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByActiveSubstanceId(Integer activesubstanceId){
		return productDao.getListProductByActiveSubstanceId(activesubstanceId);
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyId(Integer pharmacyId,boolean active){
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProduct(active);
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				//product.setActiveSubstanceId(activeSubstanceDao.findActiveSubstanceByID(product.getActiveSubstanceId().getActiveSubstanceId()));
				if(product.getActiveSubstanceId() != null){
					Activesubstance activeSubstanceTemp = activeSubstanceDao.findActiveSubstanceByID(product.getActiveSubstanceId().getActiveSubstanceId());
					if(activeSubstanceTemp != null)
						activeSubstanceTemp.setAttributeCollection(attributeDao.getAttributeListByActiveSubstanceId(activeSubstanceTemp.getActiveSubstanceId()));
					product.setActiveSubstanceId(activeSubstanceTemp);
				}
				List<Composition> listComposition = compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true);
				for (Composition composition : listComposition) {
					if(composition.getTypeCompositionId() != null){
						Typecomposition typeComposition = typeCompositionDao.findTypecompositionByID(composition.getTypeCompositionId().getTypeCompositionId());
						composition.setTypeCompositionId(typeComposition);
					}
				}
				product.setCompositionCollection(listComposition);
				List<Productattributes> listProductAttributes = productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId());
				for (Productattributes productattributes : listProductAttributes) {
					if(productattributes.getProductattribute() != null){
						Productattribute productAttribute = productAttributeDao.findProductAttributeByProductAttributeId(productattributes.getProductattribute().getProductAttributeId());
						productattributes.setProductattribute(productAttribute);
					}
				}
				product.setProductattributesCollection(listProductAttributes);
				product.setPharmacyProduct(pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId() ,product.getProductPK().getProductId()));
				res.add(product);
			}
		}
		return res;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByProviderId(Integer pharmacyId,Integer providerId ,boolean active){
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProduct(active);//getListProductByproviderId(providerId,active);
		System.out.println(listProduct);
		for (Product product : listProduct) {
			//if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
				product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
				// add it to last. eye start
				product.setPharmacyProduct(pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId() ,product.getProductPK().getProductId()));
				// add it to last. eye end
				res.add(product);
			/*
			}else
				System.out.println(" no entro****************************************************************************** ");*/
		}
		return res;
	}	
	private List<Product> addItemToProduct(Integer pharmacyId,boolean active,Integer stockId,List<Product> listProduct){
		List<Product> res = new ArrayList<Product>();
		Product p = null;
		for (Product product : listProduct){
			p = addItemsToProduct(pharmacyId, active, stockId, product);
			if(p != null)
			res.add(p);
		}
		return res;
	}
	private List<Product> addItemToProductByState(Integer pharmacyId,boolean active,Integer stockId,List<Product> listProduct,short state){
		List<Product> res = new ArrayList<Product>();
		Product p = null;
		for (Product product : listProduct){
			p = addItemsToProductByState(pharmacyId, active, stockId, product,state);
			if(p != null)
			res.add(p);
		}
		return res;
	}
	
	/*
	private List<Product> addItemToProduct(Integer pharmacyId,boolean active,Integer stockId,List<Product> listProduct,short statePackage,short stateItem){
		List<Product> res = new ArrayList<Product>();
		for (Product product : listProduct)		
			res.add(addItemsToPackageIntoProduct(pharmacyId, active, stockId, product,statePackage,stateItem));
		return res;
	}
	*/
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByActiveByStockIdByState(Integer pharmacyId,boolean active,Integer stockId,short state) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProduct(active);
		res= addItemToProductByState(pharmacyId, active, stockId, listProduct,state);
		return res;
	}
	
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByActiveByStockId(Integer pharmacyId,boolean active,Integer stockId) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProduct(active);
		res= addItemToProduct(pharmacyId, active, stockId, listProduct);
		return res;
	}
	/*
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByActiveByStockIdByState(Integer pharmacyId,boolean active,Integer stockId,short statePackage,short stateItem) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProduct(active);
		res= addItemToProduct(pharmacyId, active, stockId, listProduct,statePackage,stateItem);
		return res;
	}
	*/
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByActiveByStockIdByName(Integer pharmacyId,boolean active,Integer stockId,String name) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProductByActiveByName(active, name);
		res= addItemToProduct(pharmacyId, active, stockId, listProduct);	
		return res;
	}	
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByActiveByStockIdByCode(Integer pharmacyId,boolean active,Integer stockId,String code) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProductByActiveByCode(active,code);
		res= addItemToProduct(pharmacyId, active, stockId, listProduct);	
		return res;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByActiveByStockIdByCodeBar(Integer pharmacyId,boolean active,Integer stockId,String codeBar) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProductByActiveByCodeBar(active,codeBar);
		res= addItemToProduct(pharmacyId, active, stockId, listProduct);	
		return res;
	}
	private Product addItemsToProduct(Integer pharmacyId,boolean active,Integer stockId,Product product){
		//System.out.println(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId()+"  ***************************** ");
		
		//if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
			product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
			product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
			product.setProvider(providerDao.findProviderByProviderId(product.getProductPK().getProviderId()));
			Pharmacyproduct  pharmacyproduct = pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId(), product.getProductPK().getProductId());
			if(pharmacyproduct != null){
				List<Package> listPackageTemp = (List)packageDao.getListPackageByPharmacyProductByActive(pharmacyproduct,active);					
				List<Package> listPackage = new ArrayList<Package>();
				for (Package package1 : listPackageTemp) {
					List<Item> listItem = itemDao.getListItemByPharmacyIdByStockIdByPackageId(stockId,package1.getPackageId());
					package1.setItemCollection(listItem);
					listPackage.add(package1);
				}			
				pharmacyproduct.setPackageCollection(listPackage);
				/*
				for (Package package1 : listPackage) {
					System.out.println(package1);
					System.out.println(package1.getItemCollection());
				}
				*/
			}
			product.setPharmacyProduct(pharmacyproduct);
		//}
		
		return product;
	}
	private Product addItemsToProductByState(Integer pharmacyId,boolean active,Integer stockId,Product product,short state){
			product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
			product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
			product.setProvider(providerDao.findProviderByProviderId(product.getProductPK().getProviderId()));
			Pharmacyproduct  pharmacyproduct = pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId(), product.getProductPK().getProductId());
			if(pharmacyproduct != null){
				List<Package> listPackageTemp = (List)packageDao.getListPackageByPharmacyProductByActive(pharmacyproduct,active);					
				List<Package> listPackage = new ArrayList<Package>();
				for (Package package1 : listPackageTemp) {
					List<Item> listItem = itemDao.getListItemByPharmacyIdByStockIdByPackageIdByState(stockId, package1.getPackageId(), state);
					package1.setItemCollection(listItem);
					listPackage.add(package1);
				}			
				pharmacyproduct.setPackageCollection(listPackage);
			}
			product.setPharmacyProduct(pharmacyproduct);		
		return product;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdComplete(Integer pharmacyId,boolean active){
		List<Product> listProduct = productDao.getListProduct(active);
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
				product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
				product.setProvider(providerDao.findProviderByProviderId(product.getProductPK().getProviderId()));
				product.setActiveSubstanceId(activeSubstanceDao.findActiveSubstanceByID(product.getActiveSubstanceId().getActiveSubstanceId()));
				Pharmacyproduct  pharmacyproduct = pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId(), product.getProductPK().getProductId());
				if(pharmacyproduct != null){
					List<Package> listPackageTemp = (List)packageDao.getListPackageByPharmacyProductByActive(pharmacyproduct,active);					
					List<Package> listPackage = new ArrayList<Package>();
					for (Package package1 : listPackageTemp) {
						List<Item> listItem = itemDao.getListItemByPackageId(package1.getPackageId());
						package1.setItemCollection(listItem);
						listPackage.add(package1);
					}			
					pharmacyproduct.setPackageCollection(listPackage);
					product.setPharmacyProduct(pharmacyproduct);
				}
			}
		}
		return listProduct;
	}
	
	@Transactional(rollbackFor = {Exception.class})
	public void setFreeItemsFreePackageToProductByPharmacyIdByTempStateByActive(Integer pharmacyId,short tempState,boolean active){
		List<Product> listProduct = productDao.getListProduct(active);
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				Pharmacyproduct  pharmacyproduct = pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId(), product.getProductPK().getProductId());
				if(pharmacyproduct != null){
					List<Package> listPackageTemp = packageDao.getListPackageByPharmacyProductByActive(pharmacyproduct,active);					
					for (Package package1 : listPackageTemp) {
						boolean activeElement = false;
						List<Item> listItem = itemDao.getListItemByPackageId(package1.getPackageId());
						for (Item item : listItem) {
							if(item.getState() == (short)3 && item.getTempState() == tempState){
								Item i = itemDao.findItemByPackageIdByItemId(item.getItemPK().getPackageId(),item.getItemPK().getItemId());
								i.setState((short)1);
								i.setTempState((short)0);
								itemDao.update(i);
								activeElement = true;
							}
						}
						if(activeElement){
							if(package1.getState() == (short)3){
								Package pac = packageDao.findPackageByPackageId(package1.getPackageId());
								pac.setState((short)1);
								packageDao.update(pac);
							}
						}
					}			
				}
			}
		}
	}
	
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdCompleteByState(Integer pharmacyId,boolean active,short state){
		return getListProductByListProductByPharmacyIdCompleteByState(productDao.getListProduct(active), pharmacyId, active, state);
	}
	private List<Product> getListProductByListProductByPharmacyIdCompleteByState(List<Product> listProduct,Integer pharmacyId,boolean active,short state){
		List<Product> listProductTemp = new ArrayList<Product>();
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
				product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
				product.setProvider(providerDao.findProviderByProviderId(product.getProductPK().getProviderId()));
				product.setActiveSubstanceId(activeSubstanceDao.findActiveSubstanceByID(product.getActiveSubstanceId().getActiveSubstanceId()));
				Pharmacyproduct  pharmacyproduct = pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId(), product.getProductPK().getProductId());
				if(pharmacyproduct != null){
					List<Package> listPackageTemp = packageDao.getListPackageByPharmacyProductByActiveByState(pharmacyproduct,active,state);					
					List<Package> listPackage = new ArrayList<Package>();
					for (Package package1 : listPackageTemp) {
						List<Item> listItem = itemDao.getListItemByPackageIdByState(package1.getPackageId(),state);
						package1.setItemCollection(listItem);
						listPackage.add(package1);
					}			
					pharmacyproduct.setPackageCollection(listPackage);
				}
				product.setPharmacyProduct(pharmacyproduct);
				listProductTemp.add(product);
			}
		}
		return listProductTemp;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByProviderCompleteByState(Integer pharmacyId,Integer providerId,boolean active,short state){
		return getListProductByListProductByPharmacyIdCompleteByState(productDao.getListProductByproviderId(providerId, active), pharmacyId, active, state);
	}
	
	
	/*
	private Product addItemsToPackageIntoProduct(Integer pharmacyId,boolean active,Integer stockId,Product product,short statePackage,short stateItem){
		if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
			product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
			product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
			product.setProvider(providerDao.findProviderByProviderId(product.getProductPK().getProviderId()));
			Pharmacyproduct  pharmacyproduct = pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, product.getProductPK().getProviderId(), product.getProductPK().getProductId());
			if(pharmacyproduct != null){
				List<Package> listPackageTemp = (List)packageDao.getListPackageByPharmacyProductByActiveByState(pharmacyproduct,active,statePackage);					
				List<Package> listPackage = new ArrayList<Package>();
				for (Package package1 : listPackageTemp) {
					List<Item> listItem = itemDao.getListItemByPharmacyIdByStockIdByPackageIdByState(stockId,package1.getPackageId(),stateItem);
					package1.setItemCollection(listItem);
					listPackage.add(package1);
				}			
				pharmacyproduct.setPackageCollection(listPackage);
				product.setPharmacyProduct(pharmacyproduct);
			}
		}
		return product;
	}	
	*/	
	
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByActiveByName(Integer pharmacyId,boolean active,String name) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProductByActiveByName(active, name);
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
				product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
				res.add(product);
			}
		}
		return res;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByproviderIdByActiveByName(Integer pharmacyId,Integer providerId,boolean active,String name) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProductByproviderIdByActiveByName(providerId, active, name);
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
				product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
				res.add(product);
			}
		}
		return res;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByproviderIdByActiveByCode(Integer pharmacyId,Integer providerId,boolean active,String code) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProductByproviderIdByActiveByCode(providerId, active, code);
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
				product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
				res.add(product);
			}
		}
		return res;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByPharmacyIdByproviderIdByActiveByCodeBar(Integer pharmacyId,Integer providerId,boolean active,String codeBar) {
		List<Product> res = new ArrayList<Product>();
		List<Product> listProduct = productDao.getListProductByproviderIdByActiveByCodeBar(providerId, active, codeBar);
		for (Product product : listProduct) {
			if(product.getUserpharmacy().getUserpharmacyPK().getPharmacyId() == pharmacyId){
				product.setCompositionCollection(compositionDao.getListComposition(product.getProductPK().getProviderId(),product.getProductPK().getProductId(),true));
				product.setProductattributesCollection(productAttributesDao.getListProductAttributesByProviderIdByProductId(product.getProductPK().getProviderId(),product.getProductPK().getProductId()));
				res.add(product);
			}
		}
		return res;
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByproviderId(Integer providerId,boolean active){
		return productDao.getListProductByproviderId(providerId, active);
	}
	@Transactional(readOnly = true)
	public List<Product> getListProductByproductId(Integer productId,boolean active){
		return productDao.getListProductByproductId(productId, active);
	}
	@Transactional(readOnly = true)
	public Product searchProductByProviderIdByProductId(Integer providerId,Integer productId){
		return productDao.findByProviderIdByProductId(providerId, productId);
	}
	/*
	@Transactional(readOnly = true)
	public Product searchProductByProviderIdByProductId(Integer providerId,Integer productId,Integer pharmacyId,boolean active,Integer stockId,short statePackage,short stateItem){
		return addItemsToPackageIntoProduct(pharmacyId,active,stockId,productDao.findByProviderIdByProductId(providerId, productId),statePackage,stateItem);
		//return addItemsToProduct(pharmacyId,active,stockId,productDao.findByProviderIdByProductId(providerId, productId),state);
	}
	*/
	@Transactional(readOnly = true)
	public Product searchProductByProviderIdByProductId(Integer providerId,Integer productId,Integer pharmacyId,boolean active,Integer stockId){
		return addItemsToProduct(pharmacyId,active,stockId,productDao.findByProviderIdByProductId(providerId, productId));
	}
	
	@Transactional(readOnly = true)
	public Product searchProductByPharmacyIdByProviderIdByProductId(Integer pharmacyId,Integer providerId,Integer productId){
		Product p = productDao.findByProviderIdByProductId(providerId, productId);
		if(p != null){
			Provider providerTemp = providerDao.findProviderByProviderId(providerId);
			p.setProvider(providerTemp);
			Pharmacyproduct ppTemp = pharmacyProductDao.findPharmacyProductByPharmacyIdByProviderIdByProductId(pharmacyId, providerId ,productId);
			if(ppTemp != null){
				List<Package> listPackageTemp = (List)packageDao.getListPackageByPharmacyProductByActive(ppTemp,true);
				for (Package package1 : listPackageTemp) {
					package1.setItemCollection(itemDao.getListItemByPackageId(package1.getPackageId()));
				}
				ppTemp.setPackageCollection(listPackageTemp);
				p.setPharmacyProduct(ppTemp);
			}
		}
		return p;
	}
	@Transactional
    public void updateProduct(Product product){
		productDao.update(product);
	}
	@Transactional
	public void addProduct(Product product){
		productDao.add(product);
	}
	@Transactional
	public Integer searchProductByProductIdMax(){
		return productDao.findByProductIdMax();
	}

	
	@Transactional(readOnly = true)
	public List<Genericvalue> getListGenericValueByPharmacyIdByGroup(Integer pharmacyId,Short group){
		return genericValueDao.getListGenericValueByPharmacyIdByGroup(pharmacyId, group);
	}
	
	
	@Transactional(readOnly = true)
	public List<Productattributes> getListProductAttributes(){
		return productAttributesDao.getListProductAttributes();
	}
	@Transactional(readOnly = true)
	public List<Productattributes> getListProductAttributesByProviderId(Integer providerId){
		return productAttributesDao.getListProductAttributesByProviderId(providerId);
	}
	@Transactional(readOnly = true)
	public List<Productattributes> getListProductAttributesByProductId(Integer productId){
		return productAttributesDao.getListProductAttributesByProductId(productId);
	}
	@Transactional(readOnly = true)
	public List<Productattributes> getListProductAttributesByProductAttributeId(Integer productAttributeId){
		return productAttributesDao.getListProductAttributesByProductAttributeId(productAttributeId);
	}
	@Transactional(readOnly = true)
	public List<Productattributes> getListProductAttributesByProviderIdByProductId(Integer providerId,Integer productId){
		return productAttributesDao.getListProductAttributesByProviderIdByProductId(providerId, productId);
	}
	@Transactional(readOnly = true)
	public Productattributes searchProductAttributesByProviderIdByProductIdByProductAttributeId(Integer providerId,Integer productId,Integer productAttributeId){
		return productAttributesDao.findByProviderIdByProductIdByProductAttributeId(providerId, productId, productAttributeId);
	}		
	@Transactional
	public void removeProductAttributes(Integer providerId,Integer productId) {
		productAttributesDao.remove(providerId, productId);
	}
	@Transactional
	public void updateProductAttributes(Productattributes productAttributes){
		productAttributesDao.update(productAttributes);
	}
	@Transactional
	public void addProductAttributes(Productattributes productAttributes){
		productAttributesDao.add(productAttributes);
	}
}